﻿using System;
using System.IO;
using System.Web;
using System.Web.Hosting;

namespace OpenWaves.Web.Tests
{
    public class ReferencedProjectVirtualPathProvider : VirtualPathProvider
    {
        private readonly string referencedProjectName;

        public ReferencedProjectVirtualPathProvider(string referencedProjectName)
        {
            this.referencedProjectName = referencedProjectName;
        }

        private bool IsMyPath(string virtualPath)
        {
            if (!VirtualPathUtility.IsAppRelative(virtualPath) && Path.IsPathRooted(virtualPath))
                virtualPath = VirtualPathUtility.ToAppRelative(virtualPath);
            return virtualPath.StartsWith(String.Format("~/{0}/", this.referencedProjectName),
                                          StringComparison.OrdinalIgnoreCase);
        }

        public override bool FileExists(string virtualPath)
        {
            if (!this.IsMyPath(virtualPath))
                return base.FileExists(virtualPath);
            else
                return File.Exists(GetFilePath(virtualPath, this.referencedProjectName));
        }

        public override VirtualFile GetFile(string virtualPath)
        {
            if (this.IsMyPath(virtualPath))
                return new MyVirtualFile(this.referencedProjectName, virtualPath);
            else
                return base.GetFile(virtualPath);
        }

        private static string GetFilePath(string virtualPath, string projectName)
        {
            var relativePath = virtualPath.Substring(String.Format("~/{0}/", projectName).Length - 1);
            var applicationRoot = HttpContext.Current.Server.MapPath("~/");

            var filePath = Path.Combine(applicationRoot, "..", projectName, relativePath);
            return filePath;
        }

        private class MyVirtualFile : VirtualFile
        {
            private readonly string referencedProjectName;

            public MyVirtualFile(string referencedProjectName, string virtualPath)
                : base(virtualPath)
            {
                this.referencedProjectName = referencedProjectName;
            }

            public override Stream Open()
            {
                var filePath = GetFilePath(this.VirtualPath, this.referencedProjectName);
                return File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
            }
        }
    }
}